package net.apexes.codegen.core;

import com.querydsl.codegen.utils.model.SimpleType;
import com.querydsl.codegen.utils.model.Type;
import com.querydsl.sql.SchemaAndTable;
import com.querydsl.sql.codegen.NamingStrategy;
import com.querydsl.sql.codegen.support.ForeignKeyData;
import com.querydsl.sql.codegen.support.InverseForeignKeyData;
import net.apexes.commons.querydsl.info.ForeignKeyInfo;
import net.apexes.commons.querydsl.info.IndexInfo;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author hedyn
 */
class KeyDataConvertor {

    private final NamingStrategy namingStrategy;

    private final String packageName, prefix, suffix;


    public KeyDataConvertor(NamingStrategy namingStrategy, String packageName, String prefix, String suffix) {
        this.namingStrategy = namingStrategy;
        this.packageName = packageName;
        this.prefix = prefix;
        this.suffix = suffix;
    }

    public Collection<ForeignKeyData> toForeignKeyData(List<ForeignKeyInfo> list) {
        List<ForeignKeyData> result = new ArrayList<>();
        for (ForeignKeyInfo info : list) {
            String name = info.getName();
            String pkSchemaName = info.getPkSchema();
            String pkTableName = info.getPkTable();

            Type pkType = createType(pkSchemaName, pkTableName);
            ForeignKeyData keyData = new ForeignKeyData(name, pkSchemaName, pkTableName, pkType);
            int size = info.getLocalColumns().size();
            for (int i = 0; i < size; i++) {
                String localColumnName = info.getLocalColumns().get(i);
                String pkColumnName = info.getPkColumns().get(i);
                keyData.add(localColumnName, pkColumnName);
            }
            result.add(keyData);
        }
        return result;
    }

    public Collection<InverseForeignKeyData> toInverseForeignKeyData(List<ForeignKeyInfo> list) {
        List<InverseForeignKeyData> result = new ArrayList<>();
        for (ForeignKeyInfo info : list) {
            String name = info.getName();
            String foreignSchemaName = info.getLocalSchema();
            String foreignTableName = info.getLocalTable();

            InverseForeignKeyData keyData = new InverseForeignKeyData(name, foreignSchemaName, foreignTableName,
                    createType(foreignSchemaName, foreignTableName));
            int size = info.getLocalColumns().size();
            for (int i = 0; i < size; i++) {
                String localColumnName = info.getLocalColumns().get(i);
                String pkColumnName = info.getPkColumns().get(i);
                keyData.add(pkColumnName, localColumnName);
            }
            result.add(keyData);
        }
        return result;
    }

    public Collection<IndexData> toIndexData(List<IndexInfo> list) {
        List<IndexData> result = new ArrayList<>();
        for (IndexInfo info : list) {
            String indexSchemaName = info.getSchema();
            String indexTableName = info.getTable();
            IndexData indexData = new IndexData(info, createType(indexSchemaName, indexTableName));
            result.add(indexData);
        }
        return result;
    }

    private Type createType(String schemaName, String table) {
        SchemaAndTable schemaAndTable = new SchemaAndTable(schemaName, table);
        String packageName = this.packageName;
        String simpleName = prefix + namingStrategy.getClassName(schemaAndTable) + suffix;
        return new SimpleType(packageName + "." + simpleName, packageName, simpleName);
    }
}
